package com.atguigu.tingshu.live.api;

import com.alibaba.fastjson.JSON;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.live.util.WebSocketLocalContainerUtil;
import com.atguigu.tingshu.model.live.FromUser;
import com.atguigu.tingshu.model.live.SocketMsg;
import com.atguigu.tingshu.model.user.UserInfo;
import jakarta.websocket.*;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

/**
 * @author atguigu-mqx
 * @ClassName WebSocketApiController
 * @description: TODO
 * @date 2023年12月16日
 * @version: 1.0
 */
@Slf4j
@ServerEndpoint("/api/websocket/{liveRoomId}/{token}") // 暴露服务地址：
@Component
public class WebSocketApiController {

    //    static 作用：
    //    @Autowired
    //    private RedisTemplate redisTemplate;
    private static RedisTemplate redisTemplate;
    //  获取到redis模版服务对象
    @Autowired // 才能注入到spring 容器. 加载机制要与静态方法同步！
    public void setRedisTemplate(RedisTemplate redisTemplate){
        WebSocketApiController.redisTemplate = redisTemplate;
    }
    /**
     * 成功链接服务器的时候会触发这个方法.
     * @param session
     * @param liveRoomId
     * @param token
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("liveRoomId") Long liveRoomId,@PathParam("token") String token){
        log.info("建立连接，liveRoomId：{}， token：{}", liveRoomId, token);
        //  通过token 来获取用户数据.
        String key = RedisConstant.USER_LOGIN_KEY_PREFIX+token;
        //  从redis 获取数据
        UserInfo userInfo = (UserInfo) redisTemplate.opsForValue().get(key);
        //  用户Id
        Long userId = userInfo.getId();
        //  创建对象
        FromUser fromUser = new FromUser();
        fromUser.setUserId(userId);
        fromUser.setNickname(userInfo.getNickname());
        fromUser.setAvatarUrl(userInfo.getAvatarUrl());
        //  添加会话
        WebSocketLocalContainerUtil.addSession(userId,session);
        WebSocketLocalContainerUtil.addFromUser(userId,fromUser);
        WebSocketLocalContainerUtil.addUserIdToLiveRoom(liveRoomId,userId);

        //  提示xxx 进入直播间
        //  构建发送消息的对象
        SocketMsg socketMsg = WebSocketLocalContainerUtil.buildSocketMsg(liveRoomId, fromUser, SocketMsg.MsgTypeEnum.JOIN_CHAT, fromUser.getNickname() + "加入直播间");
        //  返回数据
        WebSocketLocalContainerUtil.sendMsg(socketMsg);
    }

    /**
     * 断开链接服务器的时候会触发这个方法.
     * @param session
     * @param liveRoomId
     * @param token
     */
    @OnClose
    public void onClose(Session session, @PathParam("liveRoomId") Long liveRoomId,@PathParam("token") String token){
        log.info("断开连接，liveRoomId：{}， token：{}", liveRoomId, token);
        //  通过token 来获取用户数据.
        String key = RedisConstant.USER_LOGIN_KEY_PREFIX+token;
        //  从redis 获取数据
        UserInfo userInfo = (UserInfo) redisTemplate.opsForValue().get(key);
        //  用户Id
        Long userId = userInfo.getId();
        //  获取用户信息对象
        FromUser fromUser = WebSocketLocalContainerUtil.getFromUser(userId);
        //  构建发送消息的对象
        SocketMsg socketMsg = WebSocketLocalContainerUtil.buildSocketMsg(liveRoomId, fromUser, SocketMsg.MsgTypeEnum.CLOSE_SOCKET, fromUser.getNickname() + "退出直播间");

        //  删除会话
        WebSocketLocalContainerUtil.removeSession(userId);
        WebSocketLocalContainerUtil.removeFromUser(userId);
        WebSocketLocalContainerUtil.removeUserIdToLiveRoom(liveRoomId,userId);
        //  提示xxx 退出直播间
        //  发送数据
        //  WebSocketLocalContainerUtil.sendMsg(socketMsg);
        //  发送消息
        redisTemplate.convertAndSend("message:list",JSON.toJSONString(socketMsg));
    }

    /**
     * 发送消息到服务器的时候会触发这个方法.
     * @param message
     */
    @OnMessage
    public void onMessage(String message){
        log.info("来自客户端的消息：{}", message);
        //        SocketMsg socketMsg = JSON.parseObject(message, SocketMsg.class);
        //        //  发送消息
        //        WebSocketLocalContainerUtil.sendMsg(socketMsg);
        //  发送消息
        redisTemplate.convertAndSend("message:list",message);
    }

    /**
     * 成功链接服务器的时候会触发这个方法.
     * @param session
     */
    @OnError
    public void onError(Session session,Throwable throwable){
        log.error("发生错误");
        throwable.printStackTrace();
    }


}
